<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Document</title>
</head>
<body>
	
	<script>
		/**
		 * 1. 原型链继承
		 * 利用原型让一个引用类型继承另一个引用类型的属性和方法，即让原型对象等于另一个类型的实例
		 */
		function Father(){
			this.value = 666;
		}
		Father.prototype.getValue = function(){
			console.log(this.value);
		}
		function Son(){}
		//Son继承Father
		Son.prototype = new Father();
		Son.prototype.constructor = Father;
		var instance = new Son();
		instance.getValue();
		
		/**
		 * instance指向Son的原型, Son的原型又指向Father的原型, getValue方法任然在Father.prototype中
		 * 但value则位于Son.prototype中, 这是因为value是一个实例属性, 而getValue是一个原型方法。
		 * 此时, instance.constructor指向的是Father。
		 **/
		function Super(){ this.color = ['red','blue','green']; }
		function Sub(){};
		//Sub继承了super
		Sub.prototype = new Super();
		var instancel = new Sub();
		instance1.colors.push('black');
		console.log(instance1.colors);//'red,blue,green,black'
		var instance2 = new Sub();
		console.log(instance2.colors);//'red,blue,green,black'
		/**
		 * 原型链继承问题：
		 * 包含引用类型值的原型属性会被所有实例共享
		 * 在创建子类型的实例时， 不能向超类型的构造函数中传递参数
		 */
		
		
		/**
		 * 2. 借用构造函数继承
		 * 
		 **/
		function Father(){
			this.colors = ['red','blue','green'];
		}
		function Son(){
			Father.call(this);
		}
		var instance1 = new Son();
		instance1.colors.push('black');
		console.log(instance1.colors); //["red", "blue", "green", "black"]
		
		var instance2 = new Son();
		console.log(instance2.colors); //["red", "blue", "green"]
		
		
		/**
		 * 3. 组合继承
		 * 
		 **/
		function Father(name){
			this.name = name;
			this.colors = ['red','blue','green'];
		}
		Father.prototype.sayName = function(){
			console.log(this.name);
		}
		function Son(name, age){
			//继承属性
			Father.call(this, name);
			this.age = age;
		}
		//继承方法
		Son.prototype = new Father();
		Son.prototype.constructor = Son;
		Son.prototype.sayAge = function(){
			console.log(this.age);
		}
		var instance1 = new Son("bai",29);
		instance1.colors.push("black");
		console.log(instance1.colors);//['red','blue','green','black']
		instance1.sayName();//"bai"
		instance1.sayAge();//29

		var instance2 = new Son("hu",27);
		console.log(instance2.colors);//['red','blue','green']
		instance2.sayName();//"hu"
		instance2.sayAge();//27
		
		/**
		 * 4. ES6继承
		 * 
		 * 一个继承语句同时存在两条继承链：一条实现属性继承，一条实现方法的继承
		 **/
		class A extends B{}
		A.__proto__ === B;  //继承属性
		A.prototype.__proto__ == B.prototype;  //继承方法
	</script>
</body>
</html>